package com.teamin.service.impl.wx;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

public class ParseXml {
	private DocumentBuilderFactory builderFactory;
	private DocumentBuilder builder;

	public ParseXml() {
		builderFactory = DocumentBuilderFactory.newInstance();
		try {
			builder = builderFactory.newDocumentBuilder();
		} catch (ParserConfigurationException e) {

		}
	}

	public void createNode(Document document, Element root, Object obj) {

		Field[] fi = obj.getClass().getFields();

		for (Field field : fi) {
			try {
				PropertyDescriptor pd2 = new PropertyDescriptor(field.getName(), obj.getClass());
				Method method = pd2.getReadMethod();
				Object value;
				value = method.invoke(obj);

				if (List.class.isAssignableFrom(field.getType())) {
					if (value != null) {
						List<?> li = (List<?>) value;
						Element node = document.createElement(field.getName());
						for (int i = 0; i < li.size(); i++) {
							Element node1 = document.createElement("item");
							createNode(document, node1, li.get(i));
							node.appendChild(node1);
						}
						root.appendChild(node);
					}

				} else {

					if (value != null) {
						Element node = document.createElement(field.getName());
						if (value instanceof String && !"".equals(value)) {
							node.appendChild(document.createCDATASection((String) value));
							root.appendChild(node);
						} else if (value instanceof Double || value instanceof Long || value instanceof Integer || value instanceof Float) {
							node.appendChild(document.createTextNode(value + ""));
							root.appendChild(node);
						} else {
							createNode(document, node, value);
						}

					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public String createXml(Object obj) {
		Document document = builder.newDocument();
		Element element = document.createElement("xml");
		createNode(document, element, obj);
		document.appendChild(element);
		return XMLtoStr(document);

	}

	public static String XMLtoStr(Document document) {
		String result = null;

		if (document != null) {
			StringWriter strWtr = new StringWriter();
			StreamResult strResult = new StreamResult(strWtr);
			TransformerFactory tfac = TransformerFactory.newInstance();
			try {
				Transformer t = tfac.newTransformer();

				t.setOutputProperty(OutputKeys.ENCODING, "utf-8");
				// t.setOutputProperty(OutputKeys.INDENT, "yes");
				t.setOutputProperty(OutputKeys.METHOD, "html");
				// t.setOutputProperty(
				// "{http://xml.apache.org/xslt}indent-amount", "4");
				t.transform(new DOMSource(document), strResult);
			} catch (Exception e) {

			}
			result = strResult.getWriter().toString();
		}

		return result;
	}

	public <T> T parse(Class<T> classs, InputStream xmlString) throws SAXException, IOException {
		// ��DocumentBuilder�����parse���������ļ�����Document����
		Document document = builder.parse(xmlString);

		NodeList allNode = document.getElementsByTagName("xml").item(0).getChildNodes();
		T t = null;
		try {
			t = classs.newInstance();
		} catch (InstantiationException | IllegalAccessException e1) {

			e1.printStackTrace();
		}
		try {
			readNode(allNode, t);
		} catch (Exception e) {

		}
		return t;
	}

	public <T> T parse(Class<T> classs, String arg0) throws SAXException, IOException {
		Document document = builder.parse(arg0);
		NodeList allNode = document.getElementsByTagName("xml").item(0).getChildNodes();
		T t = null;
		try {
			t = classs.newInstance();
		} catch (InstantiationException | IllegalAccessException e1) {

			e1.printStackTrace();
		}
		try {
			readNode(allNode, t);
		} catch (Exception e) {

		}
		return t;
	}

	private void readNode(NodeList allNode, Object t) {
		// System.out.println(allNode.getLength());
		for (int i = 0; i < allNode.getLength(); i++) {
			Node item = allNode.item(i);
			// System.out.println(item.getNodeName() + " " +
			// item.getChildNodes().getLength());
			if (item.getChildNodes().getLength() == 1) {

				if (item.getChildNodes().item(0).getChildNodes().getLength() == 0) {
					Object iteValue = item.getChildNodes().item(0).getNodeValue();
					PropertyDescriptor pd2;
					try {
						pd2 = new PropertyDescriptor(item.getNodeName(), t.getClass());
						Method method = pd2.getWriteMethod();
						method.invoke(t, iteValue);
					} catch (Exception e) {

					}

				} else {
					Object obj;
					try {
						obj = t.getClass().getField(item.getNodeName()).getType().newInstance();
						readNode(item.getChildNodes(), obj);
						PropertyDescriptor pd2 = new PropertyDescriptor(item.getNodeName(), t.getClass());
						Method method = pd2.getWriteMethod();
						method.invoke(t, obj);
					} catch (Exception e) {

					}
				}

			} else {
				// System.out.println("name = " + item.getNodeName() + " value =
				// " + item.getTextContent());
				Object obj;
				try {
					obj = t.getClass().getField(item.getNodeName()).getType().newInstance();
					readNode(item.getChildNodes(), obj);
					PropertyDescriptor pd2 = new PropertyDescriptor(item.getNodeName(), t.getClass());
					Method method = pd2.getWriteMethod();
					method.invoke(t, obj);
				} catch (Exception e) {

				}
			}
		}
	}
}
